Skip to content

feat(Flyover): export a static QA atlas - #270

Open
kyleve wants to merge 18 commits into
mainfrom
codex/static-flyover-qa-atlas
Open

feat(Flyover): export a static QA atlas#270
kyleve wants to merge 18 commits into
mainfrom
codex/static-flyover-qa-atlas

Conversation

@kyleve

@kyleve kyleve commented Aug 14, 2026

Copy link
Copy Markdown
Owner

Posted by an AI agent on kve's behalf.

Summary

  • Add ./flyover export to generate a portable, network-free Where QA atlas from native simulator captures.
  • Add ./flyover preview to validate and serve an atlas with a printed loopback or LAN URL.
  • Export Phone Light and Phone Dark by default. Repeated --profile flags select only the requested profiles, preserve order, and remove duplicates.
  • Present the full catalog through a polished canvas, grouped list, search, route navigation, state/profile playback, stable deep links, and an immersive inspector.
  • Support responsive phone and short-landscape layouts, touch-sized controls, pinch zoom, keyboard navigation, reduced motion, and full-content review.
  • Generate bounded thumbnails for catalog views while preserving native-scale captures for the inspector and raw PNG links.
  • Keep export planning generic inside Flyover and render through SnapshotKitTesting's existing serialized hosted pipeline.
  • Build every Where capture from one frozen, synthetic, in-memory WhereFlyoverWorld.
  • Preserve the previous successful artifact when validation, capture, or publication fails.

Product behavior

  • The canvas consumes precomputed group, screen, depth-band, and connector geometry from the manifest. JavaScript does not recalculate graph depth.
  • Initial framing matches native Flyover's first-group width fit and top-leading alignment. Fit actions can zoom below 10% on narrow screens, while manual zoom keeps a practical floor.
  • The floating dock owns view selection, zoom, fitting, group navigation, and filters. Its leading controls remain reachable when it overflows on mobile.
  • Search opens with / or Command-K. It finds groups, screens, states, and routes and moves focus to a visible result.
  • Cards expose native state choices and distinguish push and modal routes. Explicit route labels are preserved.
  • List mode presents the same catalog as compact grouped rows with responsive route summaries.
  • The inspector supports fit and actual-size modes. Full-content and two-axis captures use bounded, keyboard-accessible scrolling frames.
  • The URL hash preserves view, screen, state, and profile. Browser Back and Forward restore prior selections.
  • Catalog views use generated thumbnails. The inspector and raw links use the full native capture. Existing schema-1 artifacts without thumbnails remain compatible.
  • Canvas and list views load every visible screenshot. Soft preload budgets apply only to optional offscreen images.
  • Atlas chrome and screenshots do not create accidental browser selections. Search, errors, titles, and metadata remain copyable.

Correctness and native parity

  • Route navigation opens the destination's default state. Previous/next navigation preserves each screen's selected state.
  • Snapshot-backed variants preserve sizing, readiness, settle, and hook behavior. Mixed sizing requires an explicit export policy.
  • Capture profiles apply explicit interface idiom and horizontal/vertical size classes in addition to device, color, and accessibility traits. Fixed viewports retain their declared size.
  • Snapshot trait hosts remove stale overrides when a configuration changes back to inherited traits.
  • Invalid viewport measurement hooks fail during export preflight, before the first capture.
  • SnapshotKitTesting waits for the hosted key window, serializes capture access, and exits canceled work before it mutates hosted state or publishes output.
  • The native Flyover Open Spans screen continues to use Periscope.shared. Web export receives the synthetic world's isolated log system, so export does not read user or process data.
  • Manifest validation checks schema shapes, enums, ordering, references, geometry, routes, image cardinality, exact PNG assets, thumbnail assets, and exact manifest.js parity before publication.
  • The command rejects dangerous destinations and output aliases, handles publish-time races, and uses a private unique backup during atomic replacement.
  • Re-exporting into a generated directory does not make the recorded Git tree dirty. A Git status failure stops the export.
  • Preview pins the validated root directory, opens paths component-by-component without following symbolic links, rejects traversal and malformed request targets, and suppresses untrusted request logging.
  • Preview handles Ctrl-C cleanly and reports malformed markers or manifests without a traceback.

Architecture

  • Flyover owns stable web identities, export policies, profiles, manifest data, image planning, thumbnail generation, and the dependency-free static shell.
  • SnapshotKitTesting owns PNG rendering through its existing host window, capture lock, readiness hooks, settle policies, and size limits.
  • WhereUI owns the stable ID adapter, named variants, synthetic world, catalog, and hosted export entry point.
  • Tools/flyover_manifest.py owns manifest and artifact validation. Tools/flyover_preview.py owns only the HTTP server and command lifecycle.
  • The shell uses relative local assets only. It does not use fetch, packages, remote fonts, analytics, or external scripts.
  • The preview server uses Python's standard library and adds no dependency.

Measured Where artifact

A fresh phone-light export from this branch contains 5 groups, 51 screens, 112 named states, 42 routes, 112 native captures, and 112 thumbnails. The artifact is 111,456,279 bytes and completed in 129 seconds, including wrapper validation, project generation, build, hosted capture, and publication.

For the default state of all 51 screens, decoded thumbnail pixels require about 88 MiB versus about 720 MiB for the native captures, an 8.2× reduction. The browser still loads every visible card or row.

The counts are derived from the current catalog. No exporter constant stores them.

Compatibility

The feature is DEBUG-only and test-only. It changes no production data, backup, persistence, or release runtime behavior. schemaVersion: 1 remains the artifact boundary.

Testing

  • ./test --everything — 2,040 main iOS tests and 51 snapshot tests passed.
  • ./test --only 'WhereUISnapshotTests/WhereFlyoverWebExportTests/exportsHostedSmokeAtlas()' — the exact hosted smoke matrix passed.
  • Focused Flyover, SnapshotKit, SnapshotKitTesting, and WhereUI suites passed during implementation.
  • PYTHONDONTWRITEBYTECODE=1 python3 -m unittest discover -s Tools/Tests -p 'test_*.py' — 81 tests passed.
  • Shared/Flyover/Tools/Tests/flyover_test.sh — export/preview command behavior and the executable browser harness passed.
  • The browser harness covers 320 px and 390 px responsive fitting, a 20-visible-screen residency case, thumbnail/full-image selection, backward compatibility, deep links, and selection policy.
  • ./shellcheck
  • ./swiftformat --lint
  • bash -n flyover test Shared/Flyover/Tools/Tests/flyover_test.sh
  • git diff --check
  • ./flyover export --output /tmp/where-flyover-final-e81c --profile phone-light — 51 screens, 112 states, 42 routes, and 112 valid native PNGs plus thumbnails.
  • Loopback HTTP verification returned the expected index, thumbnail, and native image bytes and rejected an undeclared path.
  • Snapshot references are unchanged.

/// Throws when a settle phase cannot produce a trustworthy capture.
@MainActor
func reportIfUnsettled(
func throwIfUnsettled(

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review focus: this deliberately changes unsettled and starved captures from recorded test issues followed by image generation into typed throws. assertSnapshots still records the thrown error, while the new hosted PNG caller stops immediately and cannot publish that image. Cancellation now follows the same path through CancellationError.

@kyleve kyleve closed this Sep 1, 2026
Make the atlas canvas-first with a compact floating dock, command-palette navigation, grouped list rows, and an immersive screenshot inspector. Preserve manifest and deep-link compatibility while keeping secondary review tools available in focused panels.\n\nValidation:\n- ./flyover export --output /tmp/where-flyover-codex --profile phone-light\n- ./test FlyoverTests\n- bash Shared/Flyover/Tools/Tests/flyover_test.sh\n- ./swiftformat --lint\n- JavaScriptCore syntax parse
@kyleve kyleve reopened this Sep 3, 2026
Resolve the command-runner extraction while preserving Flyover export progress. Adapt accessibility preparation to main's throwing settle behavior.
Run the Flyover shell self-test when its module fixture is present. Keep extracted test-runner contract fixtures independent of module-specific files.
)
}

private var profileSize: CGSize {

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this duplicated from anywhere?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant